home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
StyledText.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-20
|
12KB
|
484 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "StyledText.h"
#include "Class.h"
#include "WindowSystem.h"
#include "RunArray.h"
#include "Mark.h"
#include "OrdColl.h"
#include "Error.h"
#include "Invariant.h"
#include "TextReader.h"
#include "Math.h"
extern "C" void REP(StyledText *st);
void REP(StyledText *st)
{
st->Dump();
}
InvariantChecker(StyledText);
//----- colors for BuildStylesFromString --------------------------------------
Ink *red, *green, *blue;
//----- StyledText -------------------------------------------------------------
NewMetaImpl(StyledText,GapText, (TP(charStyles), TP(paraStyles),
TP(styleHere), T(applyStyleHere)));
static TextChanges changeRec;
StyledText::StyledText(int size, Font *fd, TxtParaAlign al) : GapText(size, fd)
{
InitStyles(new_CharStyle(fd), new_ParaStyle(al));
}
StyledText::StyledText(byte *buf, int len, Font *fd, TxtParaAlign al)
: GapText(buf, len, fd)
{
InitStyles(new_CharStyle(fd), new_ParaStyle(al));
}
StyledText::StyledText(Font *fd, char* va_(fmt), ...)
{
char *buf;
va_list ap;
va_start(ap,va_(fmt));
buf= strvprintf(va_(fmt), ap);
va_end(ap);
InitStyles(new_CharStyle(fd), new_ParaStyle());
BuildStylesFromString(new_CharStyle(fd), buf);
SafeDelete(buf);
}
StyledText::~StyledText()
{
SafeDelete(charStyles);
SafeDelete(paraStyles);
}
void StyledText::InitNew()
{
GapText::InitNew();
InitStyles(new_CharStyle(gSysFont), new_ParaStyle());
}
void StyledText::InitStyles(CharStyle *cs, ParaStyle *ps)
{
charStyles= new RunArray;
paraStyles= new RunArray;
applyStyleHere= FALSE;
paraStyles->Insert(ps, 0, 0, Size());
charStyles->Insert(cs, 0, 0, Size());
}
int StyledText::GetNextFontChange(int at, CharStyle *&sp)
{
int start, end, size, lenat;
at= Math::Range(0, Size()-1, at);
sp= (CharStyle*)charStyles->RunAt(at, &start, &end, &size, &lenat);
return at+lenat;
}
void StyledText::ReplaceWithStr(byte *str,int len)
{
GapText::ReplaceWithStr(str, len);
SafeDelete(charStyles);
SafeDelete(paraStyles);
InitStyles(new_CharStyle(GetFont()), new_ParaStyle());
}
void StyledText::Cut(int from, int to)
{
int start, end, size, lenat;
CharStyle *sp= (CharStyle*)charStyles->RunAt(from, &start, &end, &size, &lenat);
applyStyleHere= FALSE;
if (start == from && size <= to - from) {
applyStyleHere= TRUE;
styleHere= sp;
}
GapText::Cut(from, to);
}
void StyledText::Dump()
{
RunArrayIter next(paraStyles);
int start, end, size, i;
fprintf(stderr, "DUMP\n");
fprintf(stderr, "Runs\n");
for (i= 0; next.Run(&start, &end, &size) != 0; i++) {
fprintf(stderr, "%d ", end);
if (!IsBreak(CharAt(end-1)))
fprintf(stderr, "!");
}
fprintf(stderr, "\n");
}
void StyledText::CheckInvariant()
{
if (GetAssertLevel() > 10)
return;
RunArrayIter next(paraStyles);
int start, end, size, i;
if (paraStyles->Size() != Size()) {
fprintf(stderr, "!!!StyledText Invariant: paraStyles: size differs! %d %d\n", paraStyles->Size(), Size());
Dump();
}
if (charStyles->Size() != Size()) {
fprintf(stderr, "!!!StyledText Invariant: charStyles: size differs! %d %d\n", paraStyles->Size(), Size());
Dump();
}
for (i= 0; next.Run(&start, &end, &size) != 0; i++) {
if (!IsBreak(CharAt(end-1)) && end < Size()) {
fprintf(stderr, "!!!StyledText Invariant: no paragraph at %d\n", end-1);
Dump();
}
}
}
void StyledText::CutParaStyles(int from, int to, int sz)
{
int pfl, pfr;
GetParaRange(from, &pfl, &pfr);
paraStyles->Cut(from, to);
paraStyles->ChangeRunSize(from, sz, eRARight);
if(pfl < Size()) {
ParaStyle *ps= GetParaStyle(pfl);
paraStyles->Insert(ps, from, pfr, pfr-from);
}
}
void StyledText::ReplaceRange(int from, int to, Text* src, int sfrom, int sto)
{
AssertInvariant(StyledText);
int sz= sto-sfrom;
DoDelayChanges dc(this);
GapText::ReplaceRange(from, to, src, sfrom, sto);
if (src->IsKindOf(StyledText)) {
StyledText *st= (StyledText*) src;
charStyles->ReplaceRange(from, to, st->charStyles, sfrom, sto);
PasteParaStyles(from, to, st->paraStyles, sfrom, sto);
return;
}
if (from != to)
CutStyles(from, to, sz);
else
paraStyles->ChangeRunSize(from, sz, eRARight);
if (applyStyleHere && sz) { // insert new run with styleHere
charStyles->Insert(styleHere, from, from, sz);
applyStyleHere= FALSE;
} else
AddChars(from, sz);
}
void StyledText::CutStyles(int from, int to, int sz)
{
int start, end, size, lenat;
CharStyle *sp= (CharStyle*)charStyles->RunAt(from, &start, &end, &size, &lenat);
if (start == from && size <= to - from) {
applyStyleHere= TRUE;
styleHere= sp;
}
CutParaStyles(from, to, sz);
charStyles->Cut(from, to);
}
void StyledText::PasteParaStyles(int from, int to, RunArray *pr, int sfrom, int sto)
{
int pfl, pfr, ptl, ptr, sz= sto-sfrom;
ParaStyle *ps;
paraStyles->ReplaceRange(from, to, pr, sfrom, sto);
GetParaRange(from, &pfl, &pfr);
GetParaRange(from+sz, &ptl, &ptr);
if(pfl == ptl) {
ps= GetParaStyle(from+sz);
paraStyles->Insert(ps, from, from+sz, sz);
} else {
ps= GetParaStyle(pfl);
paraStyles->Insert(ps, from, pfr, pfr-from);
ps= GetParaStyle(ptl);
paraStyles->Insert(ps, from+sz, ptr, ptr-from-sz);
}
}
void StyledText::AddChars(int at, int sz)
{
RArrayGrowDir g= eRALeft;
if (IsParaStart(at))
g= eRARight;
charStyles->ChangeRunSize(at, sz, g);
}
void StyledText::SetFStringVL(char *fmt, va_list ap)
{
char *buf= strvprintf(fmt, ap);
CharStyle *st= GetCharStyle(0);
BuildStylesFromString(st, buf);
SafeDelete(buf);
}
OStream &StyledText::PrintOn(OStream &s)
{
AssertInvariant(StyledText);
GapText::PrintOn(s);
return s << charStyles SP << paraStyles SP;
}
IStream &StyledText::ReadFrom(IStream &s)
{
AssertInvariant(StyledText);
GapText::ReadFrom(s);
s >> charStyles >> paraStyles;
return s;
}
IStream& StyledText::ReadFromAsPureText(IStream &s, long sizeHint)
{
GapText::ReadFromAsPureText(s, sizeHint);
SafeDelete(paraStyles);
SafeDelete(charStyles);
InitStyles(new_CharStyle(GapText::GetFont(0)), new_ParaStyle());
return s;
}
void StyledText::SetCharStyle(TxtCharProp what, int from, int to, const CharStyleSpec &st)
{
int start, end, size;
if (from == to) {
CharStyle *sp= applyStyleHere ? styleHere : GetCharStyle(Math::Max(0, from-1));
applyStyleHere= TRUE;
styleHere= gCharStyles->ChangeProperty(sp, what, st);
} else {
CharStyle **spp;
RunArray newStyles(2);
charStyles->Copy(&newStyles, from, to);
RunArrayIter next(&newStyles);
while (spp= (CharStyle**)next.RunPtr(&start, &end, &size))
*spp= gCharStyles->ChangeProperty(*spp, what, st);
charStyles->Paste(&newStyles, from, to);
GetMarkList()->RangeChanged(from, to - from);
Send(cIdNone, eTextChangedRange, changeRec(from, to));
}
}
void StyledText::BuildStylesFromString(CharStyle *cs, char *buf)
{
TextReader *reader= new TextReader(this, cs, new_ParaStyle());
if (gColor) {
red= new_RGBColor(255, 0, 0);
green= new_RGBColor(0, 255, 0);
blue= new_RGBColor(0, 0, 255);
}
for (byte *p= (byte*)buf; *p != '\0'; p++) {
if (*p == '@') {
if (*(p+1) && strchr("OUSBIPrgbx[]|_*<>+-^v", *(p+1))) {
p++;
switch (*p) {
case 'P':
reader->SetFace(eFacePlain);
break;
case 'O':
reader->ToggleFace(eFaceOutline);
break;
case 'S':
reader->ToggleFace(eFaceShadow);
break;
case 'U':
reader->ToggleFace(eFaceUnderline);
break;
case 'B':
reader->ToggleFace(eFaceBold);
break;
case 'I':
reader->ToggleFace(eFaceItalic);
break;
case 'x':
reader->SetInk(gInkBlack);
break;
case 'r':
if (gColor)
reader->SetInk(red);
break;
case 'g':
if (gColor)
reader->SetInk(green);
break;
case 'b':
if (gColor)
reader->SetInk(blue);
break;
case '+':
reader->SetSize(reader->GetSize()+4);
break;
case '-':
reader->SetSize(reader->GetSize()-4);
break;
case '[':
reader->SetParaProp(eTxtPAlign, eTxtParaLeft);
break;
case ']':
reader->SetParaProp(eTxtPAlign, eTxtParaRight);
break;
case '|':
reader->SetParaProp(eTxtPAlign, eTxtParaCenter);
break;
case '_':
reader->SetParaProp(eTxtPAlign, eTxtParaJustified);
break;
case '<':
reader->SetParaProp(eTxtPLeft, 0);
break;
case '>':
reader->SetParaProp(eTxtPLeft, 20);
break;
case '^':
reader->SetParaProp(eTxtPSpaceBefore, 20);
break;
case 'v':
reader->SetParaProp(eTxtPSpaceBefore, 0);
break;
}
} else {
p++;
if (!*p)
break;
reader->Append(*p);
}
} else
reader->Append(*p);
}
reader->Flush();
SafeDelete(reader);
CheckInvariant();
}
CharStyle *StyledText::GetCharStyle(int at)
{
int d; // ???? -1
at= Math::Range(0, Size()-1, at);
return (CharStyle*) charStyles->RunAt(at, &d, &d, &d, &d);
}
void StyledText::ReplaceCharStyles(RunArray *st, int from, int to)
{
if (to-from != st->Size())
Error("ReplaceCharStyle", "RunArray does not match text");
charStyles->Paste(st, from, to);
GetMarkList()->RangeChanged(from, to-from);
Send(cIdNone, eTextChangedRange, changeRec(from, to));
}
void StyledText::ReplaceParaStyles(RunArray *st, int from, int to)
{
if (to-from != st->Size())
Error("ReplaceParaStyles", "RunArray does not match text");
paraStyles->Paste(st, from, to);
GetMarkList()->RangeChanged(from, to-from);
Send(cIdNone, eTextChangedRange, changeRec(from, to));
}
void StyledText::ResetCurrentCharStyle()
{
if (End() != 0)
applyStyleHere= FALSE;
}
CharStyle *StyledText::GetCurrentCharStyle()
{
if (applyStyleHere)
return styleHere;
return 0;
}
RunArray *StyledText::GetCharStyles()
{
return charStyles;
}
RunArray *StyledText::GetParaStyles()
{
return paraStyles;
}
RunArray *StyledText::SetCharStyles(RunArray *st)
{
if (st->Size() != Size())
Error("StyledText", "StyleArray does not correspond to the text");
RunArray *old= charStyles;
charStyles= st;
return old;
}
RunArray *StyledText::SetParaStyles(RunArray *st)
{
if (st->Size() != Size())
Error("StyledText", "StyleArray does not correspond to the text");
RunArray *old= paraStyles;
paraStyles= st;
return old;
}
void StyledText::SetParaStyle(TxtParaProp what, int from, int to, const ParaDesc &pd)
{
int pfl, ptr, dd; // paragraph ranges
int start, end, size;
// find start and end of paragraphs
GetParaRange(from, &pfl, &dd);
if (to == from)
ptr= dd;
else if (IsPara((*this)[to-1]))
ptr= to;
else
GetParaRange(to, &dd, &ptr);
ParaStyle **spp;
RunArray newStyles(2);
paraStyles->Copy(&newStyles, pfl, ptr);
RunArrayIter next(&newStyles);
while (spp= (ParaStyle**)next.RunPtr(&start, &end, &size))
*spp= gParaStyles->ChangeProperty(*spp, what, pd);
paraStyles->Paste(&newStyles, pfl, ptr);
GetMarkList()->RangeChanged(pfl, ptr-pfl);
bool pagination= ((what & eTxtPNoBreak) == eTxtPNoBreak)
|| ((what & eTxtPKeepNext) == eTxtPKeepNext);
Send(cIdNone, eTextChangedRange, changeRec(pfl, ptr, 0, pagination));
}
ParaStyle *StyledText::GetParaStyle(int at)
{
int d;
at= Math::Range(0, Size()-1, at);
return (ParaStyle*) paraStyles->RunAt(at, &d, &d, &d, &d);
}